package top.wuhaojie.library;

import ohos.agp.components.AttrSet;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;

import java.util.ArrayList;
import java.util.List;

/**
 * lipeiquan
 *
 * @since 2021-04-22
 */
public class MultiScrollNumber extends DirectionalLayout {
    private static final int VELOCITY_DEFAULT = 15;
    private static final int TEXT_SIZE_DEFAULT = 130;
    private static final int NUMBER_SIZE_DEFAULT = 130;
    private static final double DPVAL_MULTIPLE = 2.4;
    private Context mContext;
    private List<Integer> mTargetNumbers = new ArrayList<>();
    private List<Integer> mPrimaryNumbers = new ArrayList<>();
    private List<ScrollNumber> mScrollNumbers = new ArrayList<>();
    private int mTextSize = TEXT_SIZE_DEFAULT;

    private int[] mTextColors = new int[]{ResourceTable.Color_purple01};
    private String mFontFileName;
    private int mVelocity = VELOCITY_DEFAULT;

    /**
     * 构造函数
     *
     * @param context
     * @param attrs
     */
    public MultiScrollNumber(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public MultiScrollNumber(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, String.valueOf(defStyleAttr));
        mContext = context;
        int primaryNumber = 0;
        if (attrs.getAttr("primary_number").isPresent()) {
            primaryNumber = attrs.getAttr("primary_number").get().getIntegerValue();
        }
        int targetNumber = 0;
        if (attrs.getAttr("target_number").isPresent()) {
            targetNumber = attrs.getAttr("target_number").get().getIntegerValue();
        }
        int numberSize = NUMBER_SIZE_DEFAULT;
        if (attrs.getAttr("number_size").isPresent()) {
            numberSize = attrs.getAttr("number_size").get().getIntegerValue();
        }

        setNumber(primaryNumber, targetNumber);
        setTextSize(numberSize);

        setOrientation(HORIZONTAL);
        setAlignment(LayoutAlignment.CENTER);
    }

    /**
     * 设置数字
     *
     * @param num
     */
    public void setNumber(double num) {
        if (num < 0) {
            throw new IllegalArgumentException("number value should >= 0");
        }
        resetView();

        String str = String.valueOf(num);
        char[] charArray = str.toCharArray();
        for (int i = charArray.length - 1; i >= 0; i--) {
            if (Character.isDigit(charArray[i])) {
                mTargetNumbers.add(charArray[i] - '0');
            } else {
                mTargetNumbers.add(-1);
            }
        }

        for (int i = mTargetNumbers.size() - 1; i >= 0; i--) {
            if (mTargetNumbers.get(i) != -1) {
                ScrollNumber scrollNumber = new ScrollNumber(mContext);
                scrollNumber.setTextColor(getContext().getColor(mTextColors[i % mTextColors.length]));
                scrollNumber.setVelocity(mVelocity);
                scrollNumber.setTextSize(mTextSize);
                if (!TextUtils.isEmpty(mFontFileName)) {
                    scrollNumber.setTextFont(mFontFileName);
                }
                scrollNumber.setNumber(0, mTargetNumbers.get(i), i * 10);
                mScrollNumbers.add(scrollNumber);
                addComponent(scrollNumber);
            } else {
                ComponentContainer.LayoutConfig params = new ComponentContainer.LayoutConfig(
                        ComponentContainer.LayoutConfig.MATCH_CONTENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
                Text point = new Text(mContext);
                point.setText(" . ");
                point.setTextAlignment(TextAlignment.BOTTOM);
                point.setTextColor(new Color(getContext().getColor(mTextColors[i % mTextColors.length])));
                point.setTextSize(sp2px((float) mTextSize / (float) 3));
                addComponent(point, params);
            }
        }
    }

    /**
     * 设置数字
     *
     * @param val
     */
    public void setNumber(int val) {
        resetView();
        int number = val;
        while (number > 0) {
            int i = number % 10;
            mTargetNumbers.add(i);
            number /= 10;
        }

        for (int i = mTargetNumbers.size() - 1; i >= 0; i--) {
            ScrollNumber scrollNumber = new ScrollNumber(mContext);
            scrollNumber.setTextColor(getContext().getColor(mTextColors[i % mTextColors.length]));
            scrollNumber.setVelocity(mVelocity);
            scrollNumber.setTextSize(mTextSize);
            if (!TextUtils.isEmpty(mFontFileName))
                scrollNumber.setTextFont(mFontFileName);
            scrollNumber.setNumber(0, mTargetNumbers.get(i), i * 10);
            mScrollNumbers.add(scrollNumber);
            addComponent(scrollNumber);
        }
    }

    private void resetView() {
        mTargetNumbers.clear();
        mScrollNumbers.clear();
        removeAllComponents();
    }

    /**
     * 设置数字
     *
     * @param from
     * @param to
     */
    public void setNumber(int from, int to) {
        if (to < from) {
            throw new UnsupportedOperationException("'to' value must > 'from' value");
        }
        resetView();
        // operate to
        int number = to, count = 0;
        while (number > 0) {
            int i = number % 10;
            mTargetNumbers.add(i);
            number /= 10;
            count++;
        }
        // operate from
        number = from;
        while (count > 0) {
            int i = number % 10;
            mPrimaryNumbers.add(i);
            number /= 10;
            count--;
        }

        for (int i = mTargetNumbers.size() - 1; i >= 0; i--) {
            ScrollNumber scrollNumber = new ScrollNumber(mContext);
            scrollNumber.setTextColor(getContext().getColor(mTextColors[i % mTextColors.length]));
            scrollNumber.setTextSize(mTextSize);
            if (!TextUtils.isEmpty(mFontFileName)) {
                scrollNumber.setTextFont(mFontFileName);
            }
            scrollNumber.setNumber(mPrimaryNumbers.get(i), mTargetNumbers.get(i), i * 10);
            mScrollNumbers.add(scrollNumber);
            addComponent(scrollNumber);
        }
    }

    /**
     * 设置字体颜色
     *
     * @param textColors
     */
    public void setTextColors(@ColorRes int[] textColors) {
        if (textColors == null || textColors.length == 0) {
            throw new IllegalArgumentException("color array couldn't be empty!");
        }
        mTextColors = textColors.clone();
        for (int i = mScrollNumbers.size() - 1; i >= 0; i--) {
            ScrollNumber scrollNumber = mScrollNumbers.get(i);
            scrollNumber.setTextColor(getContext().getColor(mTextColors[i % mTextColors.length]));
        }
    }

    /**
     * 设置字体大小
     *
     * @param textSize
     */
    public void setTextSize(int textSize) {
        if (textSize <= 0) {
            throw new IllegalArgumentException("text size must > 0!");
        }
        mTextSize = textSize;
        for (ScrollNumber scrollNumber : mScrollNumbers) {
            scrollNumber.setTextSize(textSize);
        }
    }

    /**
     * 设置字体格式
     *
     * @param fileName
     */
    public void setTextFont(String fileName) {
        if (TextUtils.isEmpty(fileName)) {
            throw new IllegalArgumentException("file name is null");
        }
        mFontFileName = fileName;
        for (ScrollNumber scrollNumber : mScrollNumbers) {
            scrollNumber.setTextFont(fileName);
        }
    }

    /**
     * 设置ScrollVelocity值
     *
     * @param velocity
     */
    public void setScrollVelocity(@IntRange(from = 0, to = 1000) int velocity) {
        mVelocity = velocity;
        for (ScrollNumber scrollNumber : mScrollNumbers) {
            scrollNumber.setVelocity(velocity);
        }
    }

    private int dp2px(float dpVal) {
        return (int) dpVal;
    }

    private int sp2px(float dpVal) {
        return (int) (dpVal * DPVAL_MULTIPLE);
    }
}
